import { defineStore } from "pinia";
import {
  type userType,
  store,
  router,
  resetRouter,
  routerArrays,
  storageLocal
} from "../utils";
import {
  type LoginApiResult,
  type LoginSuccessData,
  type PartialAuthData,
  type RefreshTokenResult,
  type RegisterRequest,
  postLogin,
  postRegister,
  postPlatformLogin,
  refreshTokenApi
} from "@/api/user";
import { useMultiTagsStoreHook } from "./multiTags";
import { usePermissionStoreHook } from "./permission";
import { type DataInfo, setToken, removeToken, userKey } from "@/utils/auth";
import websocketClient from "@/utils/notify";

const PARTIAL_STORAGE_KEY = "partial-auth";

function loadPartialState(): {
  action: string;
  context: Record<string, any> | null;
  token: string;
  expires: string;
} {
  try {
    const raw = sessionStorage.getItem(PARTIAL_STORAGE_KEY);
    if (!raw) return { action: "", context: null, token: "", expires: "" };
    const parsed = JSON.parse(raw);
    return {
      action: parsed?.action ?? "",
      context: parsed?.context ?? null,
      token: parsed?.token ?? "",
      expires: parsed?.expires ?? ""
    };
  } catch (error) {
    console.warn("Failed to parse partial auth state", error);
    return { action: "", context: null, token: "", expires: "" };
  }
}

function persistPartialState(state: {
  action?: string;
  context?: Record<string, any> | null;
  token?: string;
  expires?: string;
}) {
  if (!state.action && !state.token) {
    sessionStorage.removeItem(PARTIAL_STORAGE_KEY);
    return;
  }
  sessionStorage.setItem(
    PARTIAL_STORAGE_KEY,
    JSON.stringify({
      action: state.action,
      context: state.context,
      token: state.token,
      expires: state.expires
    })
  );
}

export const useUserStore = defineStore("pure-user", {
  state: (): userType => {
    const partial = loadPartialState();
    return {
      // 头像
      avatar: storageLocal().getItem<DataInfo<number>>(userKey)?.avatar ?? "",
      // 用户名
      username:
        storageLocal().getItem<DataInfo<number>>(userKey)?.username ?? "",
      // 昵称
      nickname:
        storageLocal().getItem<DataInfo<number>>(userKey)?.nickname ?? "",
      // 页面级别权限
      roles: storageLocal().getItem<DataInfo<number>>(userKey)?.roles ?? [],
      // 按钮级别权限
      permissions:
        storageLocal().getItem<DataInfo<number>>(userKey)?.permissions ?? [],
      clientType:
        storageLocal().getItem<DataInfo<number>>(userKey)?.clientType ??
        "admin",
      // 是否勾选了登录页的免登录
      isRemembered: false,
      // 登录页的免登录存储几天，默认7天
      loginDay: 7,
      verifyCode: "",
      currentPage: 0,
      partialContext: partial.context,
      partialAction: partial.action,
      partialToken: partial.token,
      partialExpires: partial.expires
    };
  },
  actions: {
    /** 存储头像 */
    SET_AVATAR(avatar: string) {
      this.avatar = avatar;
    },
    SET_CLIENT(client: string) {
      this.clientType = client;
    },
    /** 存储用户名 */
    SET_USERNAME(username: string) {
      this.username = username;
    },
    /** 存储昵称 */
    SET_NICKNAME(nickname: string) {
      this.nickname = nickname;
    },
    /** 存储角色 */
    SET_ROLES(roles: Array<string>) {
      this.roles = roles;
    },
    /** 存储按钮级别权限 */
    SET_PERMS(permissions: Array<string>) {
      this.permissions = permissions;
    },
    SET_VERIFYCODE(code: string) {
      this.verifyCode = code;
    },
    SET_CURRENTPAGE(value: number) {
      this.currentPage = value;
    },
    /** 存储是否勾选了登录页的免登录 */
    SET_ISREMEMBERED(bool: boolean) {
      this.isRemembered = bool;
    },
    /** 设置登录页的免登录存储几天 */
    SET_LOGINDAY(value: number) {
      this.loginDay = Number(value);
    },
    /** 存储部分登录上下文 */
    SET_PARTIAL(
      action: string,
      context: Record<string, any> | null,
      token = "",
      expires = ""
    ) {
      this.partialAction = action;
      this.partialContext = context;
      this.partialToken = token;
      this.partialExpires = expires;
      persistPartialState({
        action,
        context,
        token,
        expires
      });
    },
    updatePartialContext(context: Record<string, any> | null, replace = false) {
      if (replace) {
        this.partialContext = context;
      } else {
        this.partialContext = {
          ...(this.partialContext ?? {}),
          ...(context ?? {})
        };
      }
      persistPartialState({
        action: this.partialAction,
        context: this.partialContext,
        token: this.partialToken,
        expires: this.partialExpires
      });
    },
    clearPartial() {
      this.partialAction = "";
      this.partialContext = null;
      this.partialToken = "";
      this.partialExpires = "";
      persistPartialState({
        action: "",
        context: null,
        token: "",
        expires: ""
      });
    },
    /** 处理登录成功后的公共逻辑 */
    handleLoginSuccess(payload: LoginSuccessData) {
      this.SET_PARTIAL("", null);
      const {
        accessToken,
        refreshToken,
        expires,
        username,
        nickname,
        roles,
        permissions,
        profile,
        menus,
        client
      } = payload;
      const clientType = (client ?? "admin").toLowerCase();

      setToken({
        accessToken,
        refreshToken,
        expires,
        avatar: profile?.avatar ?? "",
        username,
        nickname,
        roles,
        permissions,
        clientType
      });
      this.SET_CLIENT(clientType);

      this.SET_USERNAME(username);
      this.SET_NICKNAME(nickname);
      this.SET_ROLES(roles ?? []);
      this.SET_PERMS(permissions ?? []);
      this.SET_AVATAR(profile?.avatar ?? "");

      storageLocal().setItem("async-routes", menus ?? []);

      websocketClient.init();
    },
    /** 账号密码登录（兼容旧参数） */
    async loginByUsername(data: {
      username?: string;
      phone?: string;
      password: string;
    }) {
      const phone = data.phone ?? data.username ?? "";
      const result = await postLogin({ phone, password: data.password });
      this.handleAuthResult(result);

      return result as LoginApiResult;
    },
    async loginBySms(data: { phone: string; code: string }) {
      const result = await postSmsLogin({
        phone: data.phone,
        code: data.code
      });
      this.handleAuthResult(result);
      return result as LoginApiResult;
    },
    /** 账号注册或第三方绑定 */
    async registerAccount(data: RegisterRequest) {
      const payload: RegisterRequest = {
        phone: data.phone,
        password: data.password,
        code: data.code,
        nickname: data.nickname,
        real_name: data.real_name,
        register_channel: data.register_channel,
        partial_token: data.partial_token ?? data.partialToken,
        invite_code: data.invite_code
      };

      const pendingIdentities = this.partialContext?.pending_identity;
      if (pendingIdentities) {
        payload.identities = pendingIdentities;
      }

      if (!payload.partial_token) {
        delete payload.partial_token;
      }
      if (!payload.code) {
        delete payload.code;
      }
      if (!payload.invite_code) {
        delete payload.invite_code;
      }

      const result = await postRegister(payload);
      this.handleAuthResult(result);
      return result as LoginApiResult;
    },
    async loginByPlatform(data: {
      ticket: string;
      nickname?: string;
      avatar?: string;
      client?: string;
      openid?: string;
    }) {
      const result = await postPlatformLogin(data);
      this.handleAuthResult(result);
      return result as LoginApiResult;
    },
    handleAuthResult(result?: LoginApiResult) {
      if (!result || !result.data) return;
      const data = result.data;
      if ((data as PartialAuthData).partial) {
        const partial = data as PartialAuthData;
        this.SET_PARTIAL(
          partial.incompleteAction,
          partial.context ?? null,
          partial.accessToken,
          partial.expires
        );
      } else {
        this.clearPartial();
        this.handleLoginSuccess(data as LoginSuccessData);
      }
    },
    /** 前端登出（不调用接口） */
    logOut(clearPersist = true) {
      this.username = "";
      this.roles = [];
      this.permissions = [];
      this.clientType = "admin";
      this.SET_PARTIAL("", null);
      removeToken();
      if (clearPersist) {
        try {
          storageLocal().removeItem("async-routes");
        } catch (error) {
          console.warn("清理路由缓存失败", error);
        }
      }
      usePermissionStoreHook().clearAllCachePage();
      useMultiTagsStoreHook().handleTags("equal", [...routerArrays]);
      resetRouter();
      router.push("/login");
      websocketClient.close();
    },
    /** 刷新`token` */
    async handRefreshToken(data) {
      return new Promise<RefreshTokenResult>((resolve, reject) => {
        refreshTokenApi(data)
          .then(data => {
            if (data) {
              setToken(data.data);
              websocketClient.bindUser();
              resolve(data);
            }
          })
          .catch(error => {
            reject(error);
          });
      });
    }
  }
});

export function useUserStoreHook() {
  return useUserStore(store);
}
